#include "stdafx.h"
#include "DiskMgmt.h"

HRESULT vdsLoad( IVdsService **ppService )
{
	CComPtr<IVdsServiceLoader> pLoader;
	HRESULT hr = CoCreateInstance( CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS( &pLoader ) );
	CHECK( hr, "CoCreateInstance( CLSID_VdsLoader ) failed" );

	CComPtr<IVdsService> pService;
	hr = pLoader->LoadService( NULL, &pService );
	CHECK( hr, "IVdsService::LoadService failed" );

	hr = pService->WaitForServiceReady();
	CHECK( hr, "IVdsService::WaitForServiceReady failed" );

	*ppService = pService.Detach();
	return S_OK;
}

CString sDiskInfo::getTypeString() const
{
	static CAtlMap<DWORD, const wchar_t*> theMap;

	if( theMap.GetCount() <= 0 )
	{
		theMap[ FILE_DEVICE_CD_ROM ] = L"DVD/CD-ROM drives";
		theMap[ FILE_DEVICE_DISK ] = L"Disk drives";
		theMap[ FILE_DEVICE_DVD ] = L"DVD drives";
		theMap[ FILE_DEVICE_MASS_STORAGE ] = L"Mass storage";
		theMap[ FILE_DEVICE_TAPE ] = L"Tape drives";
		theMap.Rehash();
	}

	auto p = theMap.Lookup( type );
	if( NULL != p )
		return p->m_value;
	return L"Unknown";
}

CString sDiskInfo::getStateString() const
{
	switch( state )
	{
	case eDiskState::Online:
		return L"Online";

	case eDiskState::Offline:
		return L"Offline";

	case eDiskState::Failed:
	default:
		return L"N/A";
	}
}

HRESULT vdsDiskInfo( IVdsDisk *pDisk, sDiskInfo* pStatus )
{
	VDS_DISK_PROP props;
	HRESULT hr = pDisk->GetProperties( &props );
	CHECK0( hr );
	pStatus->displayName = props.pwszFriendlyName;
	pStatus->size = props.ullSize;
	pStatus->type = props.dwDeviceType;

	switch( props.status )
	{
	case VDS_DS_ONLINE:
	case VDS_DS_NO_MEDIA:
		pStatus->state = eDiskState::Online;
		break;
	case VDS_DS_OFFLINE:
		pStatus->state = eDiskState::Offline;
		break;
	default:
		pStatus->state = eDiskState::Failed;
	}

	CoTaskMemFree( props.pwszDiskAddress );
	CoTaskMemFree( props.pwszName );
	CoTaskMemFree( props.pwszFriendlyName );
	CoTaskMemFree( props.pwszAdaptorName );
	CoTaskMemFree( props.pwszDevicePath );

	return S_OK;
}

CString sDiskInfo::getSizeString() const
{
	if( size <= 0 )
		return L"";

	const QWORD M = 1024 * 1024;
	const QWORD G = M * 1024;
	const QWORD T = G * 1024;

	double div;
	LPCTSTR suffix;
	if( size < G )
	{
		div = M;
		suffix = L"MB";
	}
	else if( size < T )
	{
		div = G;
		suffix = L"GB";
	}
	else
	{
		div = T;
		suffix = L"TB";
	}

	const double val = (double)size / div;
	int decimalDigits;
	if( val < 10 )
		decimalDigits = 2;
	else if( val < 100 )
		decimalDigits = 1;
	else
		decimalDigits = 0;

	CString res;
	res.Format( L"%.*f %s", decimalDigits, val, suffix );
	return res;
}

HRESULT vdsOnline( IVdsDisk *pDisk )
{
	CComPtr<IVdsDiskOnline> pOnline;
	HRESULT hr = pDisk->QueryInterface( &pOnline );
	CHECK0( hr );

	return pOnline->Online();
}

HRESULT vdsOffline( IVdsDisk *pDisk )
{
	CComPtr<IVdsDiskOnline> pOnline;
	HRESULT hr = pDisk->QueryInterface( &pOnline );
	CHECK0( hr );

	return pOnline->Offline();
}